import sys, os
import importlib
import pythoncom
import win32com.client
import win32com.server.util


class Constructor:
    _reg_clsctx_ = pythoncom.CLSCTX_LOCAL_SERVER  #以单独的进程运行服务，注释后将作为进程内服务。
    _reg_clsid_ = "{1520E30D-18E5-4B61-BEA9-B79EE05B337E}"
    _reg_progid_ = "Python.ModularActiveX"
    _reg_desc_ = "Python Modular COM Components"
    _public_methods_ = ['test', 'excel', 'zip']  #必须，公开给 COM 的所有方法的名称，不定义调用对象会出错误。
    _public_attrs_ = []  #公开给 COM 的所有属性名称的列表，用于读取和写入。
    _readonly_attrs_ = []  #只读属性名称的列表。

    __component = {}

    def __init__(self):
        self.__injection = Utilities()

    def __factory(self, name): #加载并加工模块
        module = None
        if name in self.__component:
            module = self.__component.get(name)
        else:
            module = importlib.import_module('modules.%s' % (name)).Handler
            module.compilation = self.__injection
            self.__component[name] = module
        return module


    def test(self):
        # return "Test Erfolgreich 11111"
        pass 


    def excel(self):
        instance = self.__factory("excel")()
        return win32com.server.util.wrap(instance)

    def zip(self):
        instance = self.__factory("zip")()
        return win32com.server.util.wrap(instance)


class Utilities:
    def __init__(self): 
        self.constants = pythoncom #调取COM常量设定

    def VARIANT(self, vt, value): #转换变量为COM类型
        return win32com.client.VARIANT(vt, value)

    def wrap(self, ob): #包装对象供COM使用
        return win32com.server.util.wrap(ob)

    def unwrap(self, ob): #解包被wrap的对象
        return win32com.server.util.unwrap(ob)

    def CreateObject(self, name):
        return win32com.client.Dispatch(name)


def setPermission():
    import win32api
    import win32con
    import pywintypes

    ACLHex = b'\x01\x00\x04\x80\x70\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x02\x00\x5c\x00\x04\x00\x00\x00\x00\x00\x14\x00\x1f\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x05\x12\x00\x00\x00\x00\x00\x18\x00\x1f\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x00\x00\x14\x00\x0b\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x14\x00\x1f\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x05\x04\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00\x01\x02\x00\x00\x00\x00\x00\x05\x20\x00\x00\x00\x20\x02\x00\x00'
    AppID = Constructor._reg_clsid_

    def writeReg(hKey, lpSubKey, lpValueName, dwType, lpData):
        try:
            hkey = win32api.RegOpenKeyEx(hKey, lpSubKey, 0, win32con.KEY_WRITE)
            win32api.RegSetValueEx(hkey, lpValueName, 0, dwType, lpData)
            win32api.RegCloseKey(hkey)
        except pywintypes.error as e:
            pass 

    writeReg(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Classes\\AppID\\%s' %(AppID), 'LaunchPermission', win32con.REG_BINARY, ACLHex)
    writeReg(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Classes\\WOW6432Node\\AppID\\%s' %(AppID), 'LaunchPermission', win32con.REG_BINARY, ACLHex)
    writeReg(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\WOW6432Node\\Classes\\AppID\\%s' %(AppID), 'LaunchPermission', win32con.REG_BINARY, ACLHex)
    writeReg(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Classes\\CLSID\\%s' %(AppID), 'AppID', win32con.REG_SZ, AppID)
    writeReg(win32con.HKEY_CLASSES_ROOT, 'AppID\\%s' %(AppID), 'LaunchPermission', win32con.REG_BINARY, ACLHex)
    writeReg(win32con.HKEY_CLASSES_ROOT, 'WOW6432Node\\AppID\\%s' %(AppID), 'LaunchPermission', win32con.REG_BINARY, ACLHex)
    writeReg(win32con.HKEY_CLASSES_ROOT, 'CLSID\\%s' %(AppID), 'AppID', win32con.REG_SZ, AppID)


if __name__ == '__main__':
    argv = sys.argv[1:]
    if '--register' in argv  or '--unregister' in argv:
        import win32com.server.register
        win32com.server.register.UseCommandLine(Constructor)
        if '--register' in argv and Constructor._reg_clsctx_ == pythoncom.CLSCTX_LOCAL_SERVER:
            setPermission()
    else:
        print("注册: python ActiveX.py --register")
        print("注销: python ActiveX.py --unregister")
